#!/bin/env/python

import sys
import re

# compile common regexes for fast matching

re_label  = re.compile("^\\s*label ([A-Za-z0-9_]+:)\\s*$")
re_begfn  = re.compile("^\\s*label begin_func_([A-Za-z0-9_]+:)\\s*$")
re_endfn  = re.compile("^\\s*label end_func_([A-Za-z0-9_]+:)\\s*$")
re_begin  = re.compile("^\\s*label begin_block_([A-Za-z0-9_]+:)\\s*$")
re_end    = re.compile("^\\s*label end_block_([A-Za-z0-9_]+:)\\s*$")
re_param  = re.compile("^\\s*param ([A-Za-z0-9_]+)\\s*$")
re_printparam = re.compile("^\\s*print-param ([A-Za-z0-9_]+)\\s*$")
re_getpar = re.compile("^\\s*get-param (int|bool|string) ([A-Za-z0-9_]+)\\s*$")
re_begcall= re.compile("^\\s*begin-call ([A-Za-z0-9_]+)\\s*$")
re_call   = re.compile("^\\s*call ([A-Za-z0-9_]+)\\s*$")
re_return = re.compile("^\\s*return ([A-Za-z0-9_]+)\\s*$")
re_decl   = re.compile("^\\s*(int|bool|string) ([A-Za-z0-9_]+)\\s*$")
re_assig  = re.compile("^\\s*([A-Za-z0-9_]+) := (-?[A-Za-z0-9_]+)\\s*$")
re_str    = re.compile("^\\s*([A-Za-z0-9_]+) := (\"[^\"]*\")\\s*$");
re_binop  = re.compile("^\\s*([A-Za-z0-9_]+) := ([A-Za-z0-9_]+) " + 
					   "(add|sub|mul|div|rem|slt|sle|sgt|sge|seq|sne|and|or)" + 
					   " ([A-Za-z0-9_]+)\\s*$")
re_unop   = re.compile("^\\s*([A-Za-z0-9_]+) := (neg) ([A-Za-z0-9_]+)\\s*$")
re_not    = re.compile("^\\s*([A-Za-z0-9_]+) := not ([A-Za-z0-9_]+)\\s*$")
re_branch = re.compile("^\\s*branch-if ([A-Za-z0-9_]+) ([A-Za-z0-9_]+)\\s*$")
re_goto   = re.compile("^\\s*goto ([A-Za-z0-9_]+)\\s*$");

re_break       = re.compile("^\\s*break\\s*$");
re_startbreak  = re.compile("^\\s*start-breakable\\s*$");
re_endbreak    = re.compile("^\\s*end-breakable\\s*$");

re_tmp    = re.compile("tmp([0-9]+)")
re_num    = re.compile("(-?[0-9]+)")

str_count = 0


# store offsets to stack for local vars
offsets = [[0, {}]]
params = []
breakables = []

def push_param(name, size):
	offsets[-1][0] += size
	offsets[-1][1][name] = offsets[-1][0]
	pass

def push_var(name, size):
	offsets[-1][0] += size
	offsets[-1][1][name] = offsets[-1][0]
	
	#print offsets

def push_context():
	offsets.append([offsets[-1][0], dict(offsets[-1][1])])
	#print offsets

def pop_context():
	size = offsets[-1][0] - offsets[-2][0]
	offsets.pop()
	
	#print offsets
	
	return size

def find_offset(name):
	return offsets[-1][0] - offsets[-1][1][name]

# ----------------------------

def start_function_call():
	push_context()
	offsets[-1][0] += 40	
	
	# save registers
	print "\taddi $sp, $sp, -32" # enough space for all registers
	for i in xrange(8):
		print "\tsw $t%s, %s($sp)" % (i, 4*i) # save each register
	
	print "\taddi $sp, $sp, -8"
	print "\tsw $fp, 4($sp)" 	# save frame pointer
	print "\tsw $ra, 0($sp)" 	# save return address
	print "\tla $fp, 0($sp)"  	# set up frame pointer
	
def end_function_call():
	pop_context()

	print "\tla $sp, 0($fp)" 	# restore stack pointer
	print "\tlw $fp, 4($sp)"	# restore frame pointer
	print "\tlw $ra, 0($sp)"	# restore return address
	print "\taddi $sp, $sp, 8"
	
	# restore registers
	for i in xrange(8):
		print "\tlw $t%s, %s($sp)" % (i, 4*i)
	print "\taddi $sp, $sp, 32"
	

# ----------------------------

print "\t.text"
ln = 0

#try:
while True:
	line = sys.stdin.readline().strip()
	ln += 1
	if not line: break

	if re_label.match(line):
		if re_begfn.match(line):
			m = re_begfn.match(line)
			print
			print m.group(1)
			print re_label.match(line).group(1)
			push_context()
		elif re_endfn.match(line):
			print re_label.match(line).group(1)
			print "\tjr $ra"
			pop_context()
		elif re_begin.match(line):
			push_context()
			print re_label.match(line).group(1)
		elif re_end.match(line):
			size = pop_context()
			print "\taddi $sp, $sp, %s" % size
			print re_label.match(line).group(1)
		else:
			print re_label.match(line).group(1)
		
	
	elif re_getpar.match(line):
		m = re_getpar.match(line)
		name = m.group(2)
		push_param(name, 4)
	
	elif re_param.match(line):
		param = re_param.match(line).group(1)
	
		if re_tmp.match(param):
			param = "$t" + re_tmp.match(param).group(1)
		else:
			param = "%s($sp)" % find_offset(param)
		
		print "\taddi $sp, $sp, -4"
		print "\tsw %s, 0($sp)" % param
	
	elif re_printparam.match(line):
		param = re_printparam.match(line).group(1)
		if re_tmp.match(param):
			print "\tmove $a0, $t%s" % re_tmp.match(param).group(1)
		else:
			print "\tlw $a0, %s($sp)" % find_offset(param)
		
	elif re_begcall.match(line):
		func = re_begcall.match(line).group(1)
		if func not in ["print_int", "print_bool", "print_string", "read_int"]:
			start_function_call()

	elif re_call.match(line):
		func = re_call.match(line).group(1)
		if func == "print_int" or func == "print_bool":
			print "\tli $v0, 1"
			print "\tsyscall \t# print_int"
		elif func == "print_string":
			print "\tli $v0, 4"
			print "\tsyscall \t# print_string"
		elif func == "read_int":
			print "\tli $v0, 5"
			print "\tsyscall \t# read_int"
		else:
			# all other functions
			print "\tjal %s" % func
			end_function_call()
		
		params = []
		
	elif re_return.match(line):
		m = re_return.match(line)
		val = "$t" + re_tmp.match(m.group(1)).group(1)
		print "\tmove $v0, %s" % val

	elif re_decl.match(line):
		# add int to stack
		m = re_decl.match(line)
		name = m.group(2)
		push_var(name, 4)
		print "\taddi $sp, $sp, -4 \t# %s %s" % (m.group(1), name)

	elif re_assig.match(line):
		m = re_assig.match(line)
		lval = m.group(1)
		rval = m.group(2)
	
		if re_tmp.match(lval):
			# assigning something to a temp
			lval = "$t" + re_tmp.match(lval).group(1)
			if re_num.match(rval):
				# assigning a number to a temp
				print "\tli %s, %s" % (lval, rval)
			elif rval == "__fc":
				# assigning a function return value to a temp
				rval = "$v0"
				print "\tmove %s, %s" % (lval, rval)
			else:
				# assigning a local variable to a temp
				rval = "%s($sp)" % find_offset(rval)
				print "\tlw %s, %s" % (lval, rval)
		else: 
			if lval == "__bc":
				# assigning a temp to a branch condition
				lval = "$s0"
				rval = "$t" + re_tmp.match(rval).group(1)
				print "\tmove %s, %s" % (lval, rval)
			
			else:
				# assigning a temp to a local variable
				lval = "%s($sp)" % find_offset(lval)
				rval = "$t" + re_tmp.match(rval).group(1)
				print "\tsw %s, %s" % (rval, lval)
	
	elif re_str.match(line):
		m = re_str.match(line)
		lval = "$t" + re_tmp.match(m.group(1)).group(1)
		rval = "str%s" % str_count
		val  = m.group(2)
		str_count += 1
		print "\t.data"
		print "%s: .asciiz %s" % (rval, val)
		print "\t.text"
		print "la %s, %s" % (lval, rval)

	elif re_binop.match(line):
		m = re_binop.match(line)
		dest = "$t" + re_tmp.match(m.group(1)).group(1)
		op1 = "$t" + re_tmp.match(m.group(2)).group(1)
		op2 = "$t" + re_tmp.match(m.group(4)).group(1)
		opcode = m.group(3)
		print "\t%s %s, %s, %s" % (opcode, dest, op1, op2)

	elif re_unop.match(line):
		m = re_unop.match(line)
		dest = "$t" + re_tmp.match(m.group(1)).group(1)
		opcode = m.group(2)
		op1 = "$t" + re_tmp.match(m.group(3)).group(1)
		print "\t%s %s, %s" % (opcode, dest, op1)
	
	elif re_not.match(line):
		m = re_not.match(line)
		dest = "$t" + re_tmp.match(m.group(1)).group(1)
		op1 = "$t" + re_tmp.match(m.group(2)).group(1)
		print "\tseq %s, %s, $0" % (dest, op1)
	
	elif re_branch.match(line):
		m = re_branch.match(line)
		true = m.group(1)
		false = m.group(2)
		print "\tbne $s0, $zero, %s" % true
		print "\tbeq $s0, $zero, %s" % false

	elif re_goto.match(line):
		m = re_goto.match(line)
		label = m.group(1)
		print "\tb %s" % label
		
	elif re_break.match(line):
		size = offsets[-1][0] - offsets[breakables[-1]][0]
		print "\taddi $sp, $sp, %s" % size
		pass
	
	elif re_startbreak.match(line):
		breakables.append(len(offsets)-1)
		pass
		
	elif re_endbreak.match(line):
		breakables.pop()
		pass
	
#except Exception as e:
#	print >> sys.stderr, "Error in line %s" % ln
#	raise e
	
print # new line at end
	
	
	
